﻿// author : David Janacek, dj-soft@seznam.cz, 2013-12-13
// company: Asseco Solution, a.s. CZ
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace Noris.Tools.AIDCCodes.UI
{
    /// <summary>
    /// Visual control (System.Windows.Forms.Control) which show QR code in Forms
    /// </summary>
    public class QControl : Control
    {
        #region Konstrukce a privátní proměnné
        /// <summary>
        /// Create a new QControl object
        /// </summary>
        public QControl()
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this._Init();
            this.Paint += new PaintEventHandler(_Paint);
            this.SizeChanged += new EventHandler(_SizeChanged);
        }
        private void _Init()
        {
            this._ErrorCorrectionLevel = QrCode.ErrorCorrectionLevel.High;
            this._ColorLight = Color.White;
            this._ColorDark = Color.Black;
            this._Time = new System.Diagnostics.Stopwatch();
            this._TimeFreq = (decimal)System.Diagnostics.Stopwatch.Frequency;
        }
        private void _SizeChanged(object sender, EventArgs e)
        {
            this.Refresh();
        }
        /// <summary>
        /// Raise TimeChanged event.
        /// </summary>
        protected virtual void OnTimeChanged()
        {
            if (this.TimeChanged != null)
                this.TimeChanged(this, EventArgs.Empty);
        }
        private System.Diagnostics.Stopwatch _Time;
        private decimal _TimeFreq;
        #endregion
        #region Prepare matrix, Paint matrix
        private void _PrepareMatrix()
        {
            this._PrepareMatrix(this.Text, true);
        }
        private void _PrepareMatrix(string text, bool force)
        {
            if (text == null) text = "";

            if (this._Matrix != null && this._Matrix.Content != null && text == this._Matrix.Content && !force)
                return;

            this._Time.Restart();
            this._Matrix = Noris.Tools.AIDCCodes.QrCode.QEncoder.Encode(text, this._ErrorCorrectionLevel, this._UseMatrixPattern);
            this._LastQrCodeEncodeTime = this._GetCurrentTime();
        }
        private void _Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(this.BackColor);
            this._PrepareMatrix(this.Text, false);

            this._Time.Restart();
            this._Matrix.PaintCodeTo(e.Graphics, this.ClientRectangle, this._ColorLight, this._ColorDark);
            this._LastQrCodePaintTime = this._GetCurrentTime();

            this.OnTimeChanged();
        }
        /// <summary>
        /// Zastaví timer a vrátí dosud uplynulý čas v sekundách
        /// </summary>
        /// <returns></returns>
        private decimal _GetCurrentTime()
        {
            this._Time.Stop();
            long ticks = this._Time.ElapsedTicks;
            return (decimal)ticks / this._TimeFreq;
        }
        #endregion
        #region Public property
        /// <summary>
        /// Content of QR code
        /// </summary>
        [Description("Content of QR code")]
        [Category("QRCode")]
        public override string Text
        {
            get { return base.Text; }
            set
            {
                this._PrepareMatrix(value, false);
                base.Text = value;
                this.Refresh();
            }
        }
        /// <summary>
        /// Correction level applied to QR code
        /// </summary>
        [Description("Correction level applied to QR code")]
        [Category("QRCode")]
        public QrCode.ErrorCorrectionLevel ErrorCorrectionLevel
        {
            get { return this._ErrorCorrectionLevel; }
            set
            {
                this._ErrorCorrectionLevel = value;
                this._PrepareMatrix();
                this.Refresh();
            }
        }
        /// <summary>
        /// Color for White points
        /// </summary>
        [Description("Color for White points")]
        [Category("QRCode")]
        public Color ColorLight
        {
            get { return this._ColorLight; }
            set
            {
                this._ColorLight = value;
                this.Refresh();
            }
        }
        /// <summary>
        /// Color for Black points
        /// </summary>
        [Description("Color for Black points")]
        [Category("QRCode")]
        public Color ColorDark
        {
            get { return this._ColorDark; }
            set
            {
                this._ColorDark = value;
                this.Refresh();
            }
        }
        /// <summary>
        /// Use this specified MatrixPattern / null = use all patterns
        /// </summary>
        [Description("Use this specified MatrixPattern / null = use all patterns")]
        [Category("QRCode")]
        public Int32? UseMatrixPattern
        {
            get { return this._UseMatrixPattern; }
            set
            {
                this._UseMatrixPattern = value;
                this._PrepareMatrix();
                this.Refresh();
            }
        }
        /// <summary>
        /// Last QR code encode time (in seconds)
        /// </summary>
        [Description("Last QR code encode time (in seconds)")]
        [Category("QRCode")]
        public decimal LastQrCodeEncodeTime
        {
            get { return this._LastQrCodeEncodeTime; }
        }
        /// <summary>
        /// Last QR code paint time (in seconds)
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        [Description("Last QR code paint time (in seconds)")]
        [Category("QRCode")]
        public decimal LastQrCodePaintTime
        {
            get { return this._LastQrCodePaintTime; }
        }
        /// <summary>
        /// Occurs whenever values LastQrCodeEncodeTime or LastQrCodePaintTime changed.
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        [Description("When LastQrTime value changed")]
        [Category("QRCode")]
        public event EventHandler TimeChanged;
        /// <summary>
        /// Matrice bodů QR kódu
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public Noris.Tools.AIDCCodes.Common.QMatrix Matrix { get { return this._Matrix; } }
        private QrCode.ErrorCorrectionLevel _ErrorCorrectionLevel;
        private Color _ColorLight;
        private Color _ColorDark;
        private Int32? _UseMatrixPattern;
        private decimal _LastQrCodeEncodeTime;
        private decimal _LastQrCodePaintTime;
        private Noris.Tools.AIDCCodes.Common.QMatrix _Matrix;
        #endregion
    }
}
